Celovit vodnik za razumevanje in implementacijo vmesne programske opreme TypeScript v aplikacijah Express.js. Raziščite napredne vzorce tipov za robustno in vzdržljivo kodo.
TypeScript Middleware: Obvladovanje vzorcev tipov vmesne programske opreme Express
Express.js, minimalistično in prilagodljivo ogrodje spletnih aplikacij Node.js, omogoča razvijalcem, da gradijo robustne in razširljive API-je in spletne aplikacije. TypeScript izboljšuje Express z dodajanjem statičnega tipkanja, izboljšuje vzdržljivost kode in zgodaj lovi napake. Funkcije vmesne programske opreme so temelj Expressa, saj vam omogočajo prestrezanje in obdelavo zahtev, preden dosežejo vaše obravnavalce poti. Ta članek raziskuje napredne vzorce tipov TypeScript za definiranje in uporabo vmesne programske opreme Express, s čimer izboljšuje varnost tipov in jasnost kode.
Razumevanje vmesne programske opreme Express
Funkcije vmesne programske opreme so funkcije, ki imajo dostop do objekta zahteve (req), objekta odziva (res) in naslednje funkcije vmesne programske opreme v ciklu zahteve-odziva aplikacije. Funkcije vmesne programske opreme lahko izvajajo naslednje naloge:
- Izvedite poljubno kodo.
- Spremenite objekt zahteve in objekt odziva.
- Končajte cikel zahteve-odziva.
- Pokličite naslednjo funkcijo vmesne programske opreme v skladu.
Funkcije vmesne programske opreme se izvajajo zaporedno, ko so dodane v aplikacijo Express. Pogosti primeri uporabe vmesne programske opreme vključujejo:
- Beleženje zahtev.
- Avtentikacija uporabnikov.
- Avtorizacija dostopa do virov.
- Validacija podatkov zahteve.
- Obravnavanje napak.
Osnovna vmesna programska oprema TypeScript
V osnovni aplikaciji TypeScript Express je lahko funkcija vmesne programske opreme videti takole:
import { Request, Response, NextFunction } from 'express';
function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`Request: ${req.method} ${req.url}`);
next();
}
export default loggerMiddleware;
Ta preprosta vmesna programska oprema beleži metodo zahteve in URL v konzolo. Razčlenimo anotacije tipov:
Request: Predstavlja objekt zahteve Express.Response: Predstavlja objekt odziva Express.NextFunction: Funkcija, ki ob klicu izvede naslednjo vmesno programsko opremo v skladu.
To vmesno programsko opremo lahko uporabite v svoji aplikaciji Express takole:
import express from 'express';
import loggerMiddleware from './middleware/loggerMiddleware';
const app = express();
const port = 3000;
app.use(loggerMiddleware);
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
Napredni vzorci tipov za vmesno programsko opremo
Čeprav je osnovni primer vmesne programske opreme funkcionalen, mu primanjkuje prilagodljivosti in varnosti tipov za bolj zapletene scenarije. Raziščimo napredne vzorce tipov, ki izboljšujejo razvoj vmesne programske opreme s TypeScript.
1. Vrste zahtev/odgovorov po meri
Pogosto boste morali razširiti objekte Request ali Response z lastnostmi po meri. Na primer, po avtentikaciji boste morda želeli dodati lastnost user objektu Request. TypeScript vam omogoča povečanje obstoječih tipov z uporabo združevanja deklaracij.
// src/types/express/index.d.ts
import { Request as ExpressRequest } from 'express';
declare global {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
// ... other user properties
};
}
}
}
export {}; // This is needed to make the file a module
V tem primeru povečujemo vmesnik Express.Request, da vključuje izbirno lastnost user. Zdaj lahko v vmesni programski opremi za preverjanje pristnosti izpolnite to lastnost:
import { Request, Response, NextFunction } from 'express';
function authenticationMiddleware(req: Request, res: Response, next: NextFunction) {
// Simulate authentication logic
const userId = req.headers['x-user-id'] as string; // Or fetch from a token, etc.
if (userId) {
// In a real application, you would fetch the user from a database
req.user = {
id: userId,
email: `user${userId}@example.com`
};
next();
} else {
res.status(401).send('Unauthorized');
}
}
export default authenticationMiddleware;
V obravnavalcih poti pa lahko varno dostopate do lastnosti req.user:
import express from 'express';
import authenticationMiddleware from './middleware/authenticationMiddleware';
const app = express();
const port = 3000;
app.use(authenticationMiddleware);
app.get('/profile', (req: Request, res: Response) => {
if (req.user) {
res.send(`Hello, ${req.user.email}! Your user ID is ${req.user.id}`);
} else {
// This should never happen if the middleware is working correctly
res.status(500).send('Internal Server Error');
}
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
2. Tovarne vmesne programske opreme
Tovarne vmesne programske opreme so funkcije, ki vračajo funkcije vmesne programske opreme. Ta vzorec je uporaben, ko morate konfigurirati vmesno programsko opremo s posebnimi možnostmi ali odvisnostmi. Na primer, razmislite o vmesni programski opremi za beleženje, ki beleži sporočila v določeno datoteko:
import { Request, Response, NextFunction } from 'express';
import fs from 'fs';
import path from 'path';
function createLoggingMiddleware(logFilePath: string) {
return (req: Request, res: Response, next: NextFunction) => {
const logMessage = `[${new Date().toISOString()}] Request: ${req.method} ${req.url}\n`;
fs.appendFile(logFilePath, logMessage, (err) => {
if (err) {
console.error('Error writing to log file:', err);
}
next();
});
};
}
export default createLoggingMiddleware;
To tovarno vmesne programske opreme lahko uporabite takole:
import express from 'express';
import createLoggingMiddleware from './middleware/loggingMiddleware';
const app = express();
const port = 3000;
const logFilePath = path.join(__dirname, 'logs', 'requests.log');
app.use(createLoggingMiddleware(logFilePath));
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
3. Asinhrona vmesna programska oprema
Funkcije vmesne programske opreme morajo pogosto izvajati asinhronne operacije, kot so poizvedbe v bazi podatkov ali klici API. Če želite pravilno obravnavati asinhronne operacije, se morate prepričati, da je funkcija next poklicana po zaključku asinhronne operacije. To lahko dosežete z uporabo async/await ali Promises.
import { Request, Response, NextFunction } from 'express';
async function asyncMiddleware(req: Request, res: Response, next: NextFunction) {
try {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log('Asynchronous operation completed');
next();
} catch (error) {
next(error); // Pass the error to the error handling middleware
}
}
export default asyncMiddleware;
Pomembno: Ne pozabite obravnavati napak v svoji asinhroni vmesni programski opremi in jih posredovati v vmesno programsko opremo za obravnavanje napak z uporabo next(error). To zagotavlja pravilno obravnavo in beleženje napak.
4. Vmesna programska oprema za obravnavanje napak
Vmesna programska oprema za obravnavanje napak je posebna vrsta vmesne programske opreme, ki obravnava napake, ki se pojavijo med ciklom zahteve-odziva. Funkcije vmesne programske opreme za obravnavanje napak imajo štiri argumente: err, req, res in next.
import { Request, Response, NextFunction } from 'express';
function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).send('Something went wrong!');
}
export default errorHandler;
Vmesno programsko opremo za obravnavanje napak morate registrirati po vseh drugih vmesnih programskih opremah in obravnavalcih poti. Express prepozna vmesno programsko opremo za obravnavanje napak po prisotnosti štirih argumentov.
import express from 'express';
import asyncMiddleware from './middleware/asyncMiddleware';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(asyncMiddleware);
app.get('/', (req, res) => {
throw new Error('Simulated error!'); // Simulate an error
});
app.use(errorHandler); // Error handling middleware MUST be registered last
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
5. Vmesna programska oprema za validacijo zahtev
Validacija zahtev je ključni vidik gradnje varnih in zanesljivih API-jev. Vmesno programsko opremo lahko uporabite za validacijo dohodnih podatkov zahtev in zagotovite, da izpolnjujejo določena merila, preden dosežejo vaše obravnavalce poti. Za validacijo zahtev lahko uporabite knjižnice, kot sta joi ali express-validator.
Tukaj je primer z uporabo express-validator:
import { Request, Response, NextFunction } from 'express';
import { body, validationResult } from 'express-validator';
const validateCreateUserRequest = [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];
export default validateCreateUserRequest;
Ta vmesna programska oprema validira polji email in password v telesu zahteve. Če validacija ne uspe, vrne odziv 400 Bad Request z nizom sporočil o napakah. To vmesno programsko opremo lahko uporabite v svojih obravnavalcih poti takole:
import express from 'express';
import validateCreateUserRequest from './middleware/validateCreateUserRequest';
const app = express();
const port = 3000;
app.post('/users', validateCreateUserRequest, (req, res) => {
// If validation passes, create the user
res.send('User created successfully!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
6. Vbrizgavanje odvisnosti za vmesno programsko opremo
Ko so vaše funkcije vmesne programske opreme odvisne od zunanjih storitev ali konfiguracij, lahko vbrizgavanje odvisnosti pomaga izboljšati testiranje in vzdrževanje. Lahko uporabite vsebnik za vbrizgavanje odvisnosti, kot je tsyringe, ali pa preprosto posredujete odvisnosti kot argumente svojim tovarnam vmesne programske opreme.
Tukaj je primer z uporabo tovarne vmesne programske opreme z vbrizgavanjem odvisnosti:
// src/services/UserService.ts
export class UserService {
async createUser(email: string, password: string): Promise {
// In a real application, you would save the user to a database
console.log(`Creating user with email: ${email} and password: ${password}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate a database operation
}
}
// src/middleware/createUserMiddleware.ts
import { Request, Response, NextFunction } from 'express';
import { UserService } from '../services/UserService';
function createCreateUserMiddleware(userService: UserService) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
await userService.createUser(email, password);
res.status(201).send('User created successfully!');
} catch (error) {
next(error);
}
};
}
export default createCreateUserMiddleware;
// src/app.ts
import express from 'express';
import createCreateUserMiddleware from './middleware/createUserMiddleware';
import { UserService } from './services/UserService';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(express.json()); // Parse JSON request bodies
const userService = new UserService();
const createUserMiddleware = createCreateUserMiddleware(userService);
app.post('/users', createUserMiddleware);
app.use(errorHandler);
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
Najboljše prakse za vmesno programsko opremo TypeScript
- Naj bodo funkcije vmesne programske opreme majhne in osredotočene. Vsaka funkcija vmesne programske opreme mora imeti eno samo odgovornost.
- Uporabite opisna imena za svoje funkcije vmesne programske opreme. Ime mora jasno nakazovati, kaj počne vmesna programska oprema.
- Pravilno obravnavajte napake. Vedno lovite napake in jih posredujte v vmesno programsko opremo za obravnavanje napak z uporabo
next(error). - Uporabite vrste zahtev/odgovorov po meri za izboljšanje varnosti tipov. Po potrebi povečajte vmesnike
RequestinResponsez lastnostmi po meri. - Uporabite tovarne vmesne programske opreme za konfiguriranje vmesne programske opreme s posebnimi možnostmi.
- Dokumentirajte svoje funkcije vmesne programske opreme. Pojasnite, kaj počne vmesna programska oprema in kako jo je treba uporabljati.
- Temeljito preizkusite svoje funkcije vmesne programske opreme. Napišite enotske teste, da zagotovite pravilno delovanje vaših funkcij vmesne programske opreme.
Zaključek
TypeScript bistveno izboljša razvoj vmesne programske opreme Express z dodajanjem statičnega tipkanja, izboljšanjem vzdržljivosti kode in zgodnjim lovljenjem napak. Z obvladovanjem naprednih vzorcev tipov, kot so vrste zahtev/odgovorov po meri, tovarne vmesne programske opreme, asinhrona vmesna programska oprema, vmesna programska oprema za obravnavanje napak in vmesna programska oprema za validacijo zahtev, lahko gradite robustne, razširljive in tipsko varne aplikacije Express. Ne pozabite upoštevati najboljših praks, da bodo vaše funkcije vmesne programske opreme majhne, osredotočene in dobro dokumentirane.